import type { CodeGenerationConfig } from "../templates/backend-frameworks"
import type { DataTable } from "../types"
import { saveAs } from "file-saver"
import JSZip from "jszip"
import { mockTables } from "../mock/data"

/**
 * 代码生成服务
 */
export class CodeGeneratorService {
  private config: CodeGenerationConfig
  private tables: DataTable[]

  constructor(config: CodeGenerationConfig, tables: DataTable[] = mockTables) {
    this.config = config
    this.tables = tables
  }

  /**
   * 生成并下载项目代码
   */
  async generateAndDownload(): Promise<void> {
    const zip = new JSZip()

    // 根据框架类型生成不同的项目结构
    switch (this.config.framework.id) {
      case "spring-boot":
        await this.generateSpringBootProject(zip)
        break
      case "express-js":
        await this.generateExpressProject(zip)
        break
      case "fastapi":
        await this.generateFastAPIProject(zip)
        break
      default:
        throw new Error(`不支持的框架: ${this.config.framework.name}`)
    }

    // 生成压缩包并下载
    const content = await zip.generateAsync({ type: "blob" })
    saveAs(content, `${this.config.projectName}.zip`)
  }

  /**
   * 生成 Spring Boot 项目
   */
  private async generateSpringBootProject(zip: JSZip): Promise<void> {
    const basePackagePath = this.config.basePackage.replace(/\./g, "/")
    const srcPath = `src/main/java/${basePackagePath}`

    // 1. 项目根文件
    zip.file("pom.xml", this.generatePomXml())
    zip.file("README.md", this.generateReadme())
    zip.file(".gitignore", this.generateGitignore())

    if (this.config.features.enableDocker) {
      zip.file("Dockerfile", this.generateDockerfile())
      zip.file("docker-compose.yml", this.generateDockerCompose())
    }

    // 2. 配置文件
    zip.file("src/main/resources/application.yml", this.generateApplicationYml())
    zip.file("src/main/resources/application-dev.yml", this.generateApplicationDevYml())
    zip.file("src/main/resources/application-prod.yml", this.generateApplicationProdYml())

    // 3. 主启动类
    zip.file(`${srcPath}/Application.java`, this.generateSpringBootMainClass())

    // 4. 配置类
    zip.file(`${srcPath}/config/WebConfig.java`, this.generateWebConfig())
    if (this.config.features.enableSwagger) {
      zip.file(`${srcPath}/config/Knife4jConfig.java`, this.generateKnife4jConfig())
    }

    // 5. 通用类
    zip.file(`${srcPath}/common/Result.java`, this.generateResultClass())
    zip.file(`${srcPath}/common/PageResult.java`, this.generatePageResultClass())
    zip.file(`${srcPath}/common/BaseEntity.java`, this.generateBaseEntityClass())

    // 6. 为每个表生成代码
    for (const table of this.tables) {
      const entityName = this.toPascalCase(table.name)

      // Entity
      zip.file(`${srcPath}/entity/${entityName}.java`, this.generateEntity(table))

      // DTO
      zip.file(`${srcPath}/dto/${entityName}DTO.java`, this.generateDTO(table))

      // VO
      zip.file(`${srcPath}/vo/${entityName}VO.java`, this.generateVO(table))

      // Repository
      zip.file(`${srcPath}/repository/${entityName}Repository.java`, this.generateRepository(table))

      // Service
      zip.file(`${srcPath}/service/${entityName}Service.java`, this.generateService(table))

      // Controller
      zip.file(`${srcPath}/controller/${entityName}Controller.java`, this.generateController(table))
    }

    // 7. SQL 脚本
    zip.file("src/main/resources/sql/schema.sql", this.generateSchemaSql())
    zip.file("src/main/resources/sql/data.sql", this.generateDataSql())
  }

  /**
   * 生成 Express.js 项目
   */
  private async generateExpressProject(zip: JSZip): Promise<void> {
    // Express.js 项目结构
    zip.file("package.json", this.generatePackageJson())
    zip.file("README.md", this.generateReadme())
    zip.file(".gitignore", this.generateNodeGitignore())
    zip.file("app.js", this.generateExpressApp())

    if (this.config.features.enableDocker) {
      zip.file("Dockerfile", this.generateNodeDockerfile())
    }

    // 配置文件
    zip.file("config/database.js", this.generateDatabaseConfig())
    zip.file("config/swagger.js", this.generateSwaggerConfig())

    // 为每个表生成代码
    for (const table of this.tables) {
      const modelName = this.toCamelCase(table.name)

      zip.file(`models/${modelName}.js`, this.generateExpressModel(table))
      zip.file(`controllers/${modelName}Controller.js`, this.generateExpressController(table))
      zip.file(`routes/${modelName}.js`, this.generateExpressRoute(table))
      zip.file(`services/${modelName}Service.js`, this.generateExpressService(table))
    }
  }

  /**
   * 生成 FastAPI 项目
   */
  private async generateFastAPIProject(zip: JSZip): Promise<void> {
    // FastAPI 项目结构
    zip.file("requirements.txt", this.generateRequirementsTxt())
    zip.file("README.md", this.generateReadme())
    zip.file(".gitignore", this.generatePythonGitignore())
    zip.file("main.py", this.generateFastAPIMain())

    if (this.config.features.enableDocker) {
      zip.file("Dockerfile", this.generatePythonDockerfile())
    }

    // 配置文件
    zip.file("config/database.py", this.generateDatabasePyConfig())
    zip.file("config/settings.py", this.generateSettingsPy())

    // 为每个表生成代码
    for (const table of this.tables) {
      const modelName = this.toSnakeCase(table.name)

      zip.file(`models/${modelName}.py`, this.generateFastAPIModel(table))
      zip.file(`schemas/${modelName}.py`, this.generateFastAPISchema(table))
      zip.file(`routers/${modelName}.py`, this.generateFastAPIRouter(table))
      zip.file(`services/${modelName}_service.py`, this.generateFastAPIService(table))
    }
  }

  // ========== 工具方法 ==========

  private toPascalCase(str: string): string {
    return str.replace(/(^|_)([a-z])/g, (_, __, char) => char.toUpperCase())
  }

  private toCamelCase(str: string): string {
    const pascal = this.toPascalCase(str)
    return pascal.charAt(0).toLowerCase() + pascal.slice(1)
  }

  private toSnakeCase(str: string): string {
    return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "")
  }

  private getCurrentDateTime(): string {
    return new Date().toISOString().slice(0, 19).replace("T", " ")
  }

  // ========== Spring Boot 模板方法 ==========

  private generatePomXml(): string {
    return `<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>${this.config.packageName}</groupId>
    <artifactId>${this.config.projectName}</artifactId>
    <version>${this.config.version}</version>
    <packaging>jar</packaging>

    <name>${this.config.projectName}</name>
    <description>${this.config.description}</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <knife4j.version>4.3.0</knife4j.version>
    </properties>

    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot Data JPA -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!-- Spring Boot Validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        ${this.config.features.enableSwagger
          ? `
        <!-- Knife4j -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>\${knife4j.version}</version>
        </dependency>`
          : ""}

        ${this.config.database.type === "mysql"
          ? `
        <!-- MySQL Driver -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>`
          : ""}

        ${this.config.database.type === "postgresql"
          ? `
        <!-- PostgreSQL Driver -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>`
          : ""}

        ${this.config.features.enableCache
          ? `
        <!-- Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>`
          : ""}

        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Spring Boot Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>`
  }

  private generateSpringBootMainClass(): string {
    return `package ${this.config.basePackage};

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * ${this.config.projectName} 应用启动类
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        System.out.println("${this.config.projectName} 启动成功！");
        System.out.println("API 文档地址: http://localhost:8080/doc.html");
    }
}`
  }

  private generateController(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)
    const queryFields = table.fields.filter(field => field.queryable)
    const _relations = table.fields.filter(field => field.relation?.enabled)

    return `package ${this.config.basePackage}.controller;

import ${this.config.basePackage}.entity.${entityName};
import ${this.config.basePackage}.service.${entityName}Service;
import ${this.config.basePackage}.dto.${entityName}DTO;
import ${this.config.basePackage}.vo.${entityName}VO;
import ${this.config.basePackage}.common.Result;
import ${this.config.basePackage}.common.PageResult;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;

/**
 * ${table.comment || table.name} 控制器
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@RestController
@RequestMapping("/api/${this.toCamelCase(table.name)}")
@Tag(name = "${table.comment || table.name}管理", description = "${table.comment || table.name}相关的增删改查操作")
@Validated
public class ${entityName}Controller {

    @Autowired
    private ${entityName}Service ${this.toCamelCase(entityName)}Service;

    /**
     * 分页查询${table.comment || table.name}
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询${table.comment || table.name}", description = "根据条件分页查询${table.comment || table.name}列表")
    @ApiResponse(responseCode = "200", description = "查询成功")
    public Result<PageResult<${entityName}VO>> page(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "页面大小", example = "10") @RequestParam(defaultValue = "10") Integer pageSize${queryFields.length > 0 ? "," : ""}
            ${queryFields.map(field =>
              `@Parameter(description = "${field.comment}") @RequestParam(required = false) ${this.getJavaType(field.type)} ${this.toCamelCase(field.name)}`
            ).join(",\n            ")}
    ) {
        ${entityName}DTO queryDTO = new ${entityName}DTO();
        ${queryFields.map(field =>
          `queryDTO.set${this.toPascalCase(field.name)}(${this.toCamelCase(field.name)});`
        ).join("\n        ")}
        
        PageResult<${entityName}VO> result = ${this.toCamelCase(entityName)}Service.page(pageNum, pageSize, queryDTO);
        return Result.success(result);
    }

    /**
     * 根据ID查询${table.comment || table.name}
     */
    @GetMapping("/{id}")
    @Operation(summary = "查询${table.comment || table.name}详情", description = "根据ID查询${table.comment || table.name}详细信息")
    public Result<${entityName}VO> getById(
            @Parameter(description = "${table.comment || table.name}ID", required = true) @PathVariable @NotNull Long id
    ) {
        ${entityName}VO result = ${this.toCamelCase(entityName)}Service.getById(id);
        return Result.success(result);
    }

    /**
     * 新增${table.comment || table.name}
     */
    @PostMapping
    @Operation(summary = "新增${table.comment || table.name}", description = "创建新的${table.comment || table.name}")
    public Result<${entityName}VO> create(
            @Parameter(description = "${table.comment || table.name}信息") @RequestBody @Valid ${entityName}DTO ${this.toCamelCase(entityName)}DTO
    ) {
        ${entityName}VO result = ${this.toCamelCase(entityName)}Service.create(${this.toCamelCase(entityName)}DTO);
        return Result.success(result);
    }

    /**
     * 更新${table.comment || table.name}
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新${table.comment || table.name}", description = "根据ID更新${table.comment || table.name}信息")
    public Result<${entityName}VO> update(
            @Parameter(description = "${table.comment || table.name}ID", required = true) @PathVariable @NotNull Long id,
            @Parameter(description = "${table.comment || table.name}信息") @RequestBody @Valid ${entityName}DTO ${this.toCamelCase(entityName)}DTO
    ) {
        ${entityName}VO result = ${this.toCamelCase(entityName)}Service.update(id, ${this.toCamelCase(entityName)}DTO);
        return Result.success(result);
    }

    /**
     * 删除${table.comment || table.name}
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除${table.comment || table.name}", description = "根据ID删除${table.comment || table.name}")
    public Result<Void> delete(
            @Parameter(description = "${table.comment || table.name}ID", required = true) @PathVariable @NotNull Long id
    ) {
        ${this.toCamelCase(entityName)}Service.delete(id);
        return Result.success();
    }
}`
  }

  private generateEntity(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)

    return `package ${this.config.basePackage}.entity;

import ${this.config.basePackage}.common.BaseEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;

/**
 * ${table.comment || table.name} 实体类
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "${table.name}")
public class ${entityName} extends BaseEntity {

    ${table.fields.map((field) => {
      const javaType = this.getJavaType(field.type)
      const annotations = []

      if (field.isPrimary) {
        annotations.push("@Id", "@GeneratedValue(strategy = GenerationType.IDENTITY)")
      }

      annotations.push(`@Column(name = "${field.name}"${field.length ? `, length = ${field.length}` : ""}${!field.nullable ? ", nullable = false" : ""})`)

      if (!field.nullable && !field.isPrimary) {
        annotations.push("@NotNull")
      }

      if (field.type === "string" && field.length) {
        annotations.push(`@Size(max = ${field.length})`)
      }

      return `    ${annotations.join("\n    ")}
    private ${javaType} ${this.toCamelCase(field.name)};`
    }).join("\n\n")}
}`
  }

  private generateApplicationYml(): string {
    const dbUrl = this.config.database.type === "mysql"
      ? `jdbc:mysql://${this.config.database.host}:${this.config.database.port}/${this.config.database.database}?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true`
      : this.config.database.type === "postgresql"
        ? `jdbc:postgresql://${this.config.database.host}:${this.config.database.port}/${this.config.database.database}?useSSL=false`
        : `mongodb://${this.config.database.host}:${this.config.database.port}/${this.config.database.database}`

    return `# ${this.config.projectName} 应用配置
server:
  port: 8080
  servlet:
    context-path: /
    encoding:
      charset: UTF-8
      enabled: true
      force: true

spring:
  application:
    name: ${this.config.projectName}
  
  profiles:
    active: dev
  
  # 数据源配置
  datasource:
    driver-class-name: ${this.config.database.type === "mysql"
      ? "com.mysql.cj.jdbc.Driver"
      : this.config.database.type === "postgresql"
        ? "org.postgresql.Driver"
        : "org.mongodb.driver.MongoDriver"}
    url: ${dbUrl}
    username: \${DB_USERNAME:${this.config.database.username}}
    password: \${DB_PASSWORD:${this.config.database.password || "your_password_here"}}
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      leak-detection-threshold: 60000

  # JPA 配置
  jpa:
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
    properties:
      hibernate:
        dialect: ${this.config.database.type === "mysql"
          ? "org.hibernate.dialect.MySQLDialect"
          : this.config.database.type === "postgresql"
            ? "org.hibernate.dialect.PostgreSQLDialect"
            : "org.hibernate.dialect.PostgreSQLDialect"}
        format_sql: true
        use_sql_comments: true
        jdbc:
          batch_size: 50
          order_inserts: true
          order_updates: true
        cache:
          use_second_level_cache: false
          use_query_cache: false

${this.config.features.enableCache
  ? `
  # Redis 配置
  data:
    redis:
      host: \${REDIS_HOST:${this.config.redis.host}}
      port: \${REDIS_PORT:${this.config.redis.port}}
      password: \${REDIS_PASSWORD:${this.config.redis.password || ""}}
      database: \${REDIS_DATABASE:${this.config.redis.database}}
      timeout: \${REDIS_TIMEOUT:${this.config.redis.timeout}}ms
      lettuce:
        pool:
          max-active: 20
          max-idle: 10
          min-idle: 5
          max-wait: 5000ms
        shutdown-timeout: 100ms`
  : ""}

${this.config.features.enableSwagger
  ? `
# Knife4j 配置
knife4j:
  enable: true
  openapi:
    title: ${this.config.projectName} API 文档
    description: ${this.config.description}
    version: ${this.config.version}
    concat-contact: true
    contact:
      name: ${this.config.author}
      email: developer@example.com
      url: https://example.com
    license:
      name: MIT License
      url: https://opensource.org/licenses/MIT
  setting:
    language: zh_cn
    enable-version: true
    enable-swagger-models: true
    enable-document-manage: true
    swagger-model-name: 实体类列表
    enable-reload-cache-parameter: true
    enable-after-script: true
    enable-filter-multipart-api-method-type: POST
    enable-filter-multipart-apis: false
    enable-request-cache: true
    enable-host: false
    enable-host-text: \${server.port}
  cors: true
  production: false`
  : ""}

${this.config.features.enableSecurity
  ? `
# Spring Security 配置
security:
  jwt:
    secret: \${JWT_SECRET:your-256-bit-secret-key-here-must-be-at-least-256-bits}
    expiration: 86400000 # 24 hours
    refresh-expiration: 604800000 # 7 days`
  : ""}

# 日志配置
logging:
  level:
    root: INFO
    ${this.config.basePackage}: DEBUG
    org.springframework.web: DEBUG
    org.springframework.security: DEBUG
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
  pattern:
    console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
  file:
    name: logs/\${spring.application.name}.log
    max-size: 100MB
    max-history: 30

# 管理端点配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
  info:
    env:
      enabled: true

# 应用信息
info:
  app:
    name: \${spring.application.name}
    version: ${this.config.version}
    description: ${this.config.description}
    author: ${this.config.author}`
  }

  private generateKnife4jConfig(): string {
    return `package ${this.config.basePackage}.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * Knife4j 配置类
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@Configuration
public class Knife4jConfig {

    /**
     * 配置 OpenAPI 基本信息
     */
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("${this.config.projectName} API 文档")
                        .version("${this.config.version}")
                        .description("${this.config.description}")
                        .contact(new Contact()
                                .name("${this.config.author}")
                                .email("developer@example.com")
                                .url("https://example.com"))
                        .license(new License()
                                .name("MIT License")
                                .url("https://opensource.org/licenses/MIT")))
                .servers(List.of(
                        new Server().url("http://localhost:8080").description("开发环境"),
                        new Server().url("https://api.example.com").description("生产环境")
                ));
    }

    /**
     * 业务模块 API 分组
     */
    @Bean
    public GroupedOpenApi businessAPI() {
        return GroupedOpenApi.builder()
                .group("业务模块")
                .pathsToMatch("/api/**")
                .build();
    }
}`
  }

  private generateResultClass(): string {
    return `package ${this.config.basePackage}.common;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

/**
 * 统一响应结果
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 */
@Data
@Schema(description = "统一响应结果")
public class Result<T> {

    @Schema(description = "响应码", example = "200")
    private Integer code;

    @Schema(description = "响应消息", example = "操作成功")
    private String message;

    @Schema(description = "响应数据")
    private T data;

    @Schema(description = "时间戳", example = "1640995200000")
    private Long timestamp;

    public Result() {
        this.timestamp = System.currentTimeMillis();
    }

    public Result(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.timestamp = System.currentTimeMillis();
    }

    public static <T> Result<T> success() {
        return new Result<>(200, "操作成功", null);
    }

    public static <T> Result<T> success(T data) {
        return new Result<>(200, "操作成功", data);
    }

    public static <T> Result<T> success(String message, T data) {
        return new Result<>(200, message, data);
    }

    public static <T> Result<T> error(String message) {
        return new Result<>(500, message, null);
    }

    public static <T> Result<T> error(Integer code, String message) {
        return new Result<>(code, message, null);
    }
}`
  }

  private generateReadme(): string {
    return `# ${this.config.projectName}

${this.config.description}

## 技术栈

- 框架: ${this.config.framework.name} ${this.config.framework.version}
- 语言: ${this.config.framework.language}
- 数据库: ${this.config.database.type.toUpperCase()}
${this.config.features.enableSwagger ? "- API 文档: Knife4j/Swagger" : ""}
${this.config.features.enableCache ? "- 缓存: Redis" : ""}
${this.config.features.enableDocker ? "- 容器化: Docker" : ""}

## 快速开始

### 环境要求

${this.config.framework.language === "Java"
  ? `
- JDK 17+
- Maven 3.6+
`
  : this.config.framework.language === "JavaScript/TypeScript"
    ? `
- Node.js 18+
- npm 或 yarn
`
    : `
- Python 3.9+
- pip
`}
- ${this.config.database.type.toUpperCase()} 数据库

### 安装依赖

\`\`\`bash
${this.config.framework.language === "Java"
  ? "mvn clean install"
  : this.config.framework.language === "JavaScript/TypeScript"
    ? "npm install"
    : "pip install -r requirements.txt"}
\`\`\`

### 配置数据库

1. 创建数据库 \`${this.config.database.database}\`
2. 修改配置文件中的数据库连接信息
3. 运行 SQL 脚本初始化表结构

### 启动应用

\`\`\`bash
${this.config.framework.language === "Java"
  ? "mvn spring-boot:run"
  : this.config.framework.language === "JavaScript/TypeScript"
    ? "npm start"
    : "python main.py"}
\`\`\`

### 访问地址

- 应用地址: http://localhost:${this.config.framework.language === "Java" ? "8080" : "3000"}
${this.config.features.enableSwagger ? "- API 文档: http://localhost:8080/doc.html" : ""}

## API 文档

${this.config.features.enableSwagger
  ? `
项目集成了 ${this.config.framework.id === "spring-boot" ? "Knife4j" : "Swagger UI"}，启动应用后可访问在线 API 文档。

### 主要功能

${this.tables.map(table => `- ${table.comment || table.name}管理`).join("\n")}
`
  : "项目暂未集成 API 文档工具。"}

## 项目结构

\`\`\`
${this.config.projectName}/
├── src/                    # 源代码
${this.config.framework.language === "Java"
  ? `├── pom.xml                 # Maven 配置
├── README.md              # 项目说明
└── Dockerfile             # Docker 配置`
  : this.config.framework.language === "JavaScript/TypeScript"
    ? `├── package.json           # npm 配置
├── README.md             # 项目说明
└── Dockerfile            # Docker 配置`
    : `├── requirements.txt       # Python 依赖
├── README.md             # 项目说明
└── Dockerfile            # Docker 配置`}
\`\`\`

## 开发说明

### 数据表

${this.tables.map(table => `
#### ${table.comment || table.name} (${table.name})

${table.fields.map(field =>
  `- ${field.name}: ${field.type}${field.nullable ? "" : " (必填)"} - ${field.comment}`
).join("\n")}
`).join("")}

## 部署

${this.config.features.enableDocker
  ? `
### Docker 部署

\`\`\`bash
# 构建镜像
docker build -t ${this.config.projectName} .

# 运行容器
docker run -p 8080:8080 ${this.config.projectName}
\`\`\`

### Docker Compose 部署

\`\`\`bash
docker-compose up -d
\`\`\`
`
  : "项目暂未配置 Docker 部署。"}

## 作者

${this.config.author}

## 许可证

MIT License
`
  }

  private generateGitignore(): string {
    if (this.config.framework.language === "Java") {
      return `# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties

# IDE
.idea/
*.iws
*.iml
*.ipr
.vscode/

# OS
.DS_Store
Thumbs.db

# Logs
logs/
*.log

# Spring Boot
application-local.yml
application-local.properties`
    } else {
      return `# Dependencies
node_modules/
*.log
npm-debug.log*

# IDE
.vscode/
.idea/

# OS
.DS_Store
Thumbs.db

# Environment
.env
.env.local`
    }
  }

  // ========== Spring Boot 其他模板方法 ==========

  private generateDTO(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)

    return `package ${this.config.basePackage}.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;

/**
 * ${table.comment || table.name} DTO
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@Data
@Schema(description = "${table.comment || table.name}数据传输对象")
public class ${entityName}DTO {

    ${table.fields.filter(f => !f.isPrimary).map((field) => {
      const javaType = this.getJavaType(field.type)
      const annotations = []

      annotations.push(`@Schema(description = "${field.comment}", example = "${this.getExampleValue(field.type)}")`)

      if (!field.nullable) {
        annotations.push(`@NotNull(message = "${field.comment}不能为空")`)
      }

      if (field.type === "string" && field.length) {
        annotations.push(`@Size(max = ${field.length}, message = "${field.comment}长度不能超过${field.length}")`)
      }

      return `    ${annotations.join("\n    ")}
    private ${javaType} ${this.toCamelCase(field.name)};`
    }).join("\n\n")}
}`
  }

  private generateVO(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)
    return `package ${this.config.basePackage}.vo;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;

/**
 * ${table.comment || table.name} VO
 * 
 * @author ${this.config.author}
 * @version ${this.config.version}
 * @since ${this.getCurrentDateTime()}
 */
@Data
@Schema(description = "${table.comment || table.name}视图对象")
public class ${entityName}VO {
    ${table.fields.map(field => `
    @Schema(description = "${field.comment}")
    private ${this.getJavaType(field.type)} ${this.toCamelCase(field.name)};`).join("")}

    @Schema(description = "创建时间")
    private LocalDateTime createTime;

    @Schema(description = "更新时间")
    private LocalDateTime updateTime;
}`
  }

  private generateRepository(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)
    return `package ${this.config.basePackage}.repository;

import ${this.config.basePackage}.entity.${entityName};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface ${entityName}Repository extends JpaRepository<${entityName}, Long>, JpaSpecificationExecutor<${entityName}> {
}`
  }

  private generateService(table: DataTable): string {
    const entityName = this.toPascalCase(table.name)
    return `package ${this.config.basePackage}.service;

import ${this.config.basePackage}.entity.${entityName};
import ${this.config.basePackage}.dto.${entityName}DTO;
import ${this.config.basePackage}.vo.${entityName}VO;
import ${this.config.basePackage}.repository.${entityName}Repository;
import ${this.config.basePackage}.common.PageResult;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class ${entityName}Service {

    @Autowired
    private ${entityName}Repository ${this.toCamelCase(entityName)}Repository;

    public PageResult<${entityName}VO> page(Integer pageNum, Integer pageSize, ${entityName}DTO queryDTO) {
        Page<${entityName}> page = ${this.toCamelCase(entityName)}Repository.findAll(PageRequest.of(pageNum - 1, pageSize));
        List<${entityName}VO> voList = page.getContent().stream().map(this::convertToVO).collect(Collectors.toList());
        return new PageResult<>(voList, page.getTotalElements(), pageNum, pageSize);
    }

    public ${entityName}VO getById(Long id) {
        ${entityName} entity = ${this.toCamelCase(entityName)}Repository.findById(id)
                .orElseThrow(() -> new RuntimeException("${table.comment || table.name}不存在"));
        return convertToVO(entity);
    }

    public ${entityName}VO create(${entityName}DTO dto) {
        ${entityName} entity = new ${entityName}();
        BeanUtils.copyProperties(dto, entity);
        entity = ${this.toCamelCase(entityName)}Repository.save(entity);
        return convertToVO(entity);
    }

    public ${entityName}VO update(Long id, ${entityName}DTO dto) {
        ${entityName} entity = ${this.toCamelCase(entityName)}Repository.findById(id)
                .orElseThrow(() -> new RuntimeException("${table.comment || table.name}不存在"));
        BeanUtils.copyProperties(dto, entity, "id");
        entity = ${this.toCamelCase(entityName)}Repository.save(entity);
        return convertToVO(entity);
    }

    public void delete(Long id) {
        ${this.toCamelCase(entityName)}Repository.deleteById(id);
    }

    private ${entityName}VO convertToVO(${entityName} entity) {
        ${entityName}VO vo = new ${entityName}VO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}`
  }

  private generateWebConfig(): string {
    return `package ${this.config.basePackage}.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableJpaAuditing
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(3600);
    }
}`
  }

  private generatePageResultClass(): string {
    return `package ${this.config.basePackage}.common;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;

@Data
@Schema(description = "分页结果")
public class PageResult<T> {
    @Schema(description = "数据列表")
    private List<T> records;
    @Schema(description = "总记录数")
    private Long total;
    @Schema(description = "当前页码")
    private Integer current;
    @Schema(description = "页面大小")
    private Integer size;
    @Schema(description = "总页数")
    private Integer pages;

    public PageResult() {}

    public PageResult(List<T> records, Long total, Integer current, Integer size) {
        this.records = records;
        this.total = total;
        this.current = current;
        this.size = size;
        this.pages = (int) Math.ceil((double) total / size);
    }
}`
  }

  private generateBaseEntityClass(): string {
    return `package ${this.config.basePackage}.common;

import jakarta.persistence.*;
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;

@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
    @CreatedDate
    @Column(name = "create_time", nullable = false, updatable = false)
    private LocalDateTime createTime;

    @LastModifiedDate
    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;
}`
  }

  private generateApplicationDevYml(): string {
    return `# 开发环境配置
spring:
  datasource:
    username: ${this.config.database.username}
    password: ${this.config.database.password || "dev_password_123"}
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2
      
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        use_sql_comments: true

${this.config.features.enableCache
  ? `
  data:
    redis:
      host: ${this.config.redis.host}
      port: ${this.config.redis.port}
      password: ${this.config.redis.password || ""}
      database: ${this.config.redis.database}
      timeout: ${this.config.redis.timeout}ms`
  : ""}

# 开发环境日志配置
logging:
  level:
    root: INFO
    ${this.config.basePackage}: DEBUG
    org.springframework.web: DEBUG
    org.springframework.security: DEBUG
    org.hibernate.SQL: DEBUG
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
  pattern:
    console: "%clr(%d{HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

# 开发环境管理端点
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

# Knife4j 开发环境配置
knife4j:
  production: false
  cors: true`
  }

  private generateApplicationProdYml(): string {
    return `# 生产环境配置
spring:
  datasource:
    username: \${DB_USERNAME:${this.config.database.username}}
    password: \${DB_PASSWORD:${this.config.database.password || "CHANGE_ME_IN_PRODUCTION"}}
    hikari:
      maximum-pool-size: 50
      minimum-idle: 10
      connection-timeout: 20000
      idle-timeout: 300000
      max-lifetime: 1200000
      leak-detection-threshold: 60000
      
  jpa:
    hibernate:
      ddl-auto: validate  # 生产环境建议使用 validate 或 none
    show-sql: false
    properties:
      hibernate:
        format_sql: false
        use_sql_comments: false
        jdbc:
          batch_size: 100

${this.config.features.enableCache
  ? `
  data:
    redis:
      host: \${REDIS_HOST:${this.config.redis.host}}
      port: \${REDIS_PORT:${this.config.redis.port}}
      password: \${REDIS_PASSWORD:${this.config.redis.password || "CHANGE_ME_IN_PRODUCTION"}}
      database: \${REDIS_DATABASE:${this.config.redis.database}}
      timeout: \${REDIS_TIMEOUT:${this.config.redis.timeout}}ms
      lettuce:
        pool:
          max-active: 50
          max-idle: 20
          min-idle: 10`
  : ""}

# 生产环境日志配置
logging:
  level:
    root: WARN
    ${this.config.basePackage}: INFO
    org.springframework.web: WARN
    org.springframework.security: WARN
    org.hibernate.SQL: WARN
  file:
    name: logs/\${spring.application.name}-prod.log
    max-size: 500MB
    max-history: 60
  pattern:
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"

# 生产环境管理端点（限制暴露）
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
      base-path: /actuator
  endpoint:
    health:
      show-details: never
  server:
    port: 9090  # 使用不同端口提高安全性

# Knife4j 生产环境配置
knife4j:
  production: true
  cors: false

# 生产环境安全配置
security:
  require-ssl: true
  jwt:
    secret: \${JWT_SECRET:CHANGE_THIS_IN_PRODUCTION_TO_A_SECURE_256_BIT_KEY}
    expiration: 3600000  # 1 hour (shorter in production)
    refresh-expiration: 86400000  # 24 hours`
  }

  private generateSchemaSql(): string {
    return this.tables.map(table => `CREATE TABLE ${table.name} (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  ${table.fields.filter(f => !f.isPrimary).map(f => `${f.name} ${this.getSqlType(f.type, f.length)}`).join(",\n  ")},
  create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
  update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);`).join("\n\n")
  }

  private generateDataSql(): string {
    return `-- 初始化数据\n-- INSERT INTO table_name (column1, column2) VALUES ('value1', 'value2');`
  }

  private generateDockerfile(): string {
    return `FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/${this.config.projectName}-${this.config.version}.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]`
  }

  private generateDockerCompose(): string {
    return `version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    depends_on:
      - db
  db:
    image: ${this.config.database.type === "mysql" ? "mysql:8.0" : "postgres:15"}
    environment:
      ${this.config.database.type === "mysql" ? "MYSQL_ROOT_PASSWORD: 123456" : "POSTGRES_PASSWORD: 123456"}
    ports:
      - "${this.config.database.port}:${this.config.database.type === "mysql" ? "3306" : "5432"}"`
  }

  private getSqlType(fieldType: string, length?: number): string {
    const typeMap: Record<string, string> = {
      string: length ? `VARCHAR(${length})` : "VARCHAR(255)",
      text: "TEXT",
      int: "INT",
      bigint: "BIGINT",
      boolean: "TINYINT(1)",
      date: "DATE",
      datetime: "DATETIME"
    }
    return typeMap[fieldType] || "VARCHAR(255)"
  }

  // Express.js 方法
  private generatePackageJson(): string {
    return ""
  }

  private generateExpressApp(): string {
    return ""
  }

  private generateDatabaseConfig(): string {
    return ""
  }

  private generateSwaggerConfig(): string {
    return ""
  }

  private generateExpressModel(_table: DataTable): string {
    return ""
  }

  private generateExpressController(_table: DataTable): string {
    return ""
  }

  private generateExpressRoute(_table: DataTable): string {
    return ""
  }

  private generateExpressService(_table: DataTable): string {
    return ""
  }

  private generateNodeDockerfile(): string {
    return ""
  }

  private generateNodeGitignore(): string {
    return ""
  }

  // FastAPI 方法
  private generateRequirementsTxt(): string {
    return ""
  }

  private generateFastAPIMain(): string {
    return ""
  }

  private generateDatabasePyConfig(): string {
    return ""
  }

  private generateSettingsPy(): string {
    return ""
  }

  private generateFastAPIModel(_table: DataTable): string {
    return ""
  }

  private generateFastAPISchema(_table: DataTable): string {
    return ""
  }

  private generateFastAPIRouter(_table: DataTable): string {
    return ""
  }

  private generateFastAPIService(_table: DataTable): string {
    return ""
  }

  private generatePythonDockerfile(): string {
    return ""
  }

  private generatePythonGitignore(): string {
    return ""
  }

  private getJavaType(fieldType: string): string {
    const typeMap: Record<string, string> = {
      string: "String",
      text: "String",
      int: "Integer",
      bigint: "Long",
      decimal: "BigDecimal",
      float: "Float",
      double: "Double",
      boolean: "Boolean",
      date: "LocalDate",
      datetime: "LocalDateTime",
      timestamp: "LocalDateTime"
    }
    return typeMap[fieldType] || "String"
  }

  private getExampleValue(fieldType: string): string {
    const exampleMap: Record<string, string> = {
      string: "示例文本",
      text: "这是一段示例文本内容",
      int: "1",
      bigint: "1",
      decimal: "99.99",
      float: "99.99",
      double: "99.99",
      boolean: "true",
      date: "2025-01-01",
      datetime: "2025-01-01 12:00:00",
      timestamp: "2025-01-01 12:00:00"
    }
    return exampleMap[fieldType] || "示例值"
  }
}
